import { constantRoutes } from '@/router/constant'
import { asyncRoutes } from '@/router/async'

/**
 * 判断路由的权限是否包含在用户所拥有的权限里面
 * @param permissions 用户拥有的权限
 * @param route  路由对象
 */
function hasPermission(permissions, route) {
  if (permissions.includes("*")) {
   //console.warn("警告：该用户拥有全部权限")
    return true;
  }
  if (route.meta && route.meta.permissions) {
    const routePermissions = route.meta.permissions;
    //求两个数组的交集,就能得到是否该菜单有权限访问，有其中一个即可
    const result = permissions.filter(p => routePermissions.includes(p));
    //交集就算是个[]空数组，结果也是true，所以要交集的长度大于1才能为true
    return result.length > 0;
  } else {
    return true
  }
}

/**
 * 递归过滤子菜单
 * 
 * @param routes asyncRoutes
 * @param roles
 */
export function filterAsyncRoutes(routes, permissions) {
  const res = []
  routes.forEach(route => {
    const tmp = { ...route }
    if (hasPermission(permissions, tmp)) {
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, permissions)
      }
      res.push(tmp)
    }
  })
  return res
}

const state = {
  routes: [],
  addRoutes: []
}

const mutations = {
  SET_ROUTES: (state, routes) => {
    state.addRoutes = routes
    state.routes = constantRoutes.concat(routes)
  }
}

const actions = {
  /**
   * 根据权限生成路由,符合RBAC新解定义，基于资源的权限管理
   * 而不是基于校色来生成路由
   * @param  commit 利用参数解构赋值ccommit变量context.commit,context是action特有的
   *                和store实例具有相同方法和属性的一个对象
   * @param {Array} permissions 
   */
  generateRoutes({ commit }, permissions) {
    //将权限数组映射到权限字符串数组
    const permissionsAsStr = permissions.map((p) => {
      return p.permissionFlag;
    })
    return new Promise(resolve => {
      //根据权限过滤路由资源
      let accessedRoutes = filterAsyncRoutes(asyncRoutes, permissionsAsStr)
      commit('SET_ROUTES', accessedRoutes)
      resolve(accessedRoutes)
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}
